#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

int data[4] = {0};
int flag[4] = {0}; // 标志位 1代表数字 2代表字母
pthread_mutex_t mutex;
pthread_cond_t cond_1, cond_2, cond_3; // 条件变量
int r_index = 0, w_index = 0, count = 0;
int num = 0, let = 0; // 计数器,记录数字字母的个数
void *thread1(void *arg)
{ // 循环写数字
  while (1)
  {
    pthread_mutex_lock(&mutex);
    while (count == 4)
    {
      pthread_cond_wait(&cond_3, &mutex);
    }
    while (data[w_index] != 0)
    {
      w_index++;
      w_index %= 4;
    }

    data[w_index] = rand() % 100 + 1; // 随机产生范围为1-100的数
    printf("写入数字为%d\n", data[w_index]);
    flag[w_index] = 1; // 设置标志位为1
    num++;             // 数字个数加1
    w_index++;
    w_index %= 4;
    count++;
    pthread_cond_signal(&cond_1);
    pthread_mutex_unlock(&mutex);
    sleep(rand() % 3);
  }
}
void *thread2(void *arg)
{ // 循环写字母
  while (1)
  {
    pthread_mutex_lock(&mutex);
    while (count == 4)
    {
      pthread_cond_wait(&cond_3, &mutex);
    }
    while (data[w_index] != 0)
    {
      w_index++;
      w_index %= 4;
    }
    data[w_index] = 'A' + rand() % 26; // 随机产生范围为A-Z的字母
    printf("写入字母为%c\n", data[w_index]);
    flag[w_index] = 2; // 设置标志位为2
    let++;             // 字母个数加1
    w_index++;
    w_index %= 4;
    count++;
    pthread_cond_signal(&cond_2);
    pthread_mutex_unlock(&mutex);
    sleep(rand() % 3);
  }
}

void *thread3(void *arg)
{ // 循环读数字
  while (1)
  {
    pthread_mutex_lock(&mutex);
    while (count == 0 || num == 0)
    {
      pthread_cond_wait(&cond_1, &mutex);
    }
    while (data[r_index] == 0 || flag[r_index] != 1)
    {
      r_index++;
      r_index %= 4;
    }
    printf("读出数字为%d\n", data[r_index]);
    data[r_index] = 0; // 将数据置为0
    flag[r_index] = 0;
    num--;
    count--; // 减少计数器
    r_index++;
    r_index %= 4;
    pthread_cond_broadcast(&cond_3); // 唤醒所有写线程
    pthread_mutex_unlock(&mutex);
    sleep(rand() % 3);
  }
}

void *thread4(void *arg)
{ // 循环读字母
  while (1)
  {
    pthread_mutex_lock(&mutex);
    while (count == 0 || let == 0)
    {
      pthread_cond_wait(&cond_2, &mutex);
    }
    while (data[r_index] == 0 || flag[r_index] != 2)
    {
      r_index++;
      r_index %= 4;
    }
    printf("读出字母为%c\n", data[r_index]);
    data[r_index] = 0; // 将数据置为0
    flag[r_index] = 0;
    let--;
    count--; // 减少计数器
    r_index++;
    r_index %= 4;
    pthread_cond_broadcast(&cond_3);

    pthread_mutex_unlock(&mutex);
    sleep(rand() % 3);
  }
}
int main()
{
  pthread_t tid1, tid2, tid3, tid4;
  int ret;
  // 初始化互斥锁
  pthread_mutex_init(&mutex, NULL);

  // 初始化条件变量
  pthread_cond_init(&cond_1, NULL); // 数字
  pthread_cond_init(&cond_2, NULL); // 字母
  pthread_cond_init(&cond_3, NULL); // 空间

  // 创建线程
  ret = pthread_create(&tid1, NULL, thread1, NULL);
  if (ret != 0)
  {
    printf("pthread_create error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_create(&tid2, NULL, thread2, NULL);
  if (ret != 0)
  {
    printf("pthread_create error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_create(&tid3, NULL, thread3, NULL);
  if (ret != 0)
  {
    printf("pthread_create error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_create(&tid4, NULL, thread4, NULL);
  if (ret != 0)
  {
    printf("pthread_create error: %s\n", strerror(ret));
    exit(1);
  }

  // 等待线程结束
  ret = pthread_join(tid1, NULL);
  if (ret != 0)
  {
    printf("pthread_join error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_join(tid2, NULL);
  if (ret != 0)
  {
    printf("pthread_join error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_join(tid3, NULL);
  if (ret != 0)
  {
    printf("pthread_join error: %s\n", strerror(ret));
    exit(1);
  }
  ret = pthread_join(tid4, NULL);
  if (ret != 0)
  {
    printf("pthread_join error: %s\n", strerror(ret));
    exit(1);
  }

  // 销毁互斥锁和条件变量
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&cond_1);
  pthread_cond_destroy(&cond_2);
  pthread_cond_destroy(&cond_3);

  return 0;
}